#pragma once

#include <jsoncpp/json/json.h>
#include <memory>
#include <sstream>
#include <string>
#include <iostream>

const std::string sep = "\r\n";

// 123\r\n{json}\r\n
bool Encode(std::string &message)
{
    if (message.size() == 0)
    {
        return false; // 字符串长度为0就不予处理
    }

    std::string tmp = std::to_string(message.size()) + sep + message + sep;
    message = tmp;
    return true;
}

// 进行解析报头
// 我们的解析报头的工作要麻烦一点
bool Decode(std::string &pakage, std::string *cotent)
{
    // 开局我们先找我们规定好的分割符,分隔符存在，那么报头就一定存在。
    auto pos = pakage.find(sep);
    if (pos == std::string::npos)
    {
        // 说明没找到
        return false; // 不用继续处理
    }

    // 提取报头，知晓内容长度
    std::string code_len_str = pakage.substr(0, pos);
    int code_len = std::stoi(code_len_str); // 转化为整形

    // 计算完整消息长度
    int code_len_total = code_len_str.size() + code_len + 2 * sep.size(); // 这里要加上两个分隔符的长度

    if (code_len_total > pakage.size())
    {
        // 说明传过来的数据不完整，长度不符合预期，不予处理
        return false;
    }

    // 处理提取消息字符串
    *cotent = pakage.substr(pos + sep.size(), code_len);

    // 从消息字符串中处理掉已经接收的部分，把传输失败的数据不予处理
    pakage.erase(0, code_len_total); // 其实这里还有处理，但是等我们后续网络代码时再来研究

    return true;
}

class Request // 用来表示表示客户端发送给服务端的计算请求
{
public:
    Request()
    {
    }
    Request(int x, int y, char oper) : _x(x),
                                       _y(y),
                                       _oper(oper)
    {
    }

    // 序列化函数：将当前对象转换为 JSON 格式的字符串
    // 参数：
    //   - out_string: 输出参数，用于存储生成的 JSON 字符串
    // 返回值：
    //   - bool: 理论上可以返回是否序列化成功，但当前实现总是返回 true
    bool Serialize(std::string &out_string)
    {
        // 1. 创建 JSON 根节点对象
        Json::Value root;

        // 2. 将成员变量填充到 JSON 对象中
        // 注意：这里使用与成员变量相同的名字作为 JSON 字段名
        root["_x"] = _x;       // 序列化第一个操作数
        root["_y"] = _y;       // 序列化第二个操作数
        root["_oper"] = _oper; // 序列化操作符

        // 3. 创建 JSON 写入器
        Json::StreamWriterBuilder wbuilder;                                     // 写入器构建器
        std::unique_ptr<Json::StreamWriter> writer(wbuilder.newStreamWriter()); // 创建写入器

        // 4. 将 JSON 数据写入字符串流
        std::stringstream ss;     // 创建字符串流
        writer->write(root, &ss); // 将 JSON 数据写入流

        // 5. 获取最终的 JSON 字符串
        out_string = ss.str(); // 将字符串流内容赋给输出参数

        // 6. 返回成功
        return true;
    }

    int Get_x() const
    {
        return _x;
    }

    int Get_y() const
    {
        return _y;
    }
    char Get_oper() const
    {
        return _oper;
    }

    // 反序列化函数：将 JSON 格式的字符串解析并填充到当前对象
    // 参数：
    //   - in_string: 输入参数，包含要解析的 JSON 字符串
    // 返回值：
    //   - bool: 返回反序列化是否成功
    bool Deserialize(std::string &in_string)
    {
        // 1. 创建 JSON 根节点对象和解析器
        Json::Value root;    // 用于存储解析后的 JSON 数据
        Json::Reader reader; // JSON 解析器

        // 2. 尝试解析输入的 JSON 字符串
        bool parsingSuccessful = reader.parse(in_string, root);

        // 3. 检查解析是否成功
        if (!parsingSuccessful)
        {
            // 输出解析错误信息（用于调试）
            std::cout << "Failed to parse JSON: "
                      << reader.getFormattedErrorMessages() << std::endl;
            return false; // 返回失败
        }

        // 4. 从 JSON 对象中提取数据并赋值给成员变量
        // 注意：这里假设 JSON 字段名与代码中的不同（没有下划线前缀）
        _x = root["_x"].asInt();       // 提取第一个操作数并转为 int
        _y = root["_y"].asInt();       // 提取第二个操作数并转为 int
        _oper = root["_oper"].asInt(); // 提取操作符并转为 int（实际应为 char,但char可以当做ASCII码存储）

        // 5. 返回成功
        return true;
    }

private:
    int _x;
    int _y;     // 规定x与y都是int类型的整数
    char _oper; // 表示运算符号
};

class Response // 表示服务端返回给客户端的计算结果
{
public:
    Response()
    {
    }
    Response(int result, int code) : _result(result),
                                     _code(code)
    {
    }

    // 序列化函数：将当前对象转换为 JSON 格式的字符串
    // 参数：
    //   - out_string: 输出参数，用于存储生成的 JSON 字符串
    // 返回值：
    //   - bool: 理论上可以返回是否序列化成功，但当前实现总是返回 true
    bool Serialize(std::string &out_string)
    {
        // 1. 创建 JSON 根节点对象
        Json::Value root;

        // 2. 将成员变量填充到 JSON 对象中
        // 注意：这里使用与成员变量相同的名字作为 JSON 字段名
        root["_result"] = _result; // 序列化我们的返回值
        root["_code"] = _code;     // 序列化错误码

        // 3. 创建 JSON 写入器
        Json::StreamWriterBuilder wbuilder;                                     // 写入器构建器
        std::unique_ptr<Json::StreamWriter> writer(wbuilder.newStreamWriter()); // 创建写入器

        // 4. 将 JSON 数据写入字符串流
        std::stringstream ss;     // 创建字符串流
        writer->write(root, &ss); // 将 JSON 数据写入流

        // 5. 获取最终的 JSON 字符串
        out_string = ss.str(); // 将字符串流内容赋给输出参数

        // 6. 返回成功
        return true;
    }

    // 反序列化函数：将 JSON 格式的字符串解析并填充到当前对象
    // 参数：
    //   - in_string: 输入参数，包含要解析的 JSON 字符串
    // 返回值：
    //   - bool: 返回反序列化是否成功
    bool Deserialize(std::string &in_string)
    {
        // 1. 创建 JSON 根节点对象和解析器
        Json::Value root;    // 用于存储解析后的 JSON 数据
        Json::Reader reader; // JSON 解析器

        // 2. 尝试解析输入的 JSON 字符串
        bool parsingSuccessful = reader.parse(in_string, root);

        // 3. 检查解析是否成功
        if (!parsingSuccessful)
        {
            // 输出解析错误信息（用于调试）
            std::cout << "Failed to parse JSON: "
                      << reader.getFormattedErrorMessages() << std::endl;
            return false; // 返回失败
        }

        // 4. 从 JSON 对象中提取数据并赋值给成员变量
        // 注意：这里假设 JSON 字段名与代码中的不同（没有下划线前缀）
        _code = root["_code"].asInt();

        _result = root["_result"].asInt();

        // 5. 返回成功
        return true;
    }

    int Result() const
    {
        return _result;
    }
    int Code() const
    {
        return _code;
    }
    void SetResult(int res)
    {
        _result = res;
    }
    void SetCode(int c)
    {
        _code = c;
    }

private:
    int _result; // 计算的结果返回
    int _code;   // 约定好的返回码，0为计算成功，1表示一些计算错误
};